/**
2 * Interface Elements for jQuery
3 * 3D Carousel
4 *
5 * http://interface.eyecon.ro
6 *
7 * Copyright (c) 2006 Stefan Petre
8 * Dual licensed under the MIT (MIT-LICENSE.txt)
9 * and GPL (GPL-LICENSE.txt) licenses.
10 *
11 */
12/**
13 * Created a 3D Carousel from a list of images, with reflections and animated by mouse position
14 *
15 * @example window.onload =
16 * function()
17 * {
18 * $('#carousel').Carousel(
19 * {
20 * itemWidth: 110,
21 * itemHeight: 62,
22 * itemMinWidth: 50,
23 * items: 'a',
24 * reflections: .5,
25 * rotationSpeed: 1.8
26 * }
27 * );
28 * }
29 * HTML
30 * <div id="carousel">
31 * <a href="" title=""><img src="" width="100%" /></a>
32 * <a href="" title=""><img src="" width="100%" /></a>
33 * <a href="" title=""><img src="" width="100%" /></a>
34 * <a href="" title=""><img src="" width="100%" /></a>
35 * <a href="" title=""><img src="" width="100%" /></a>
36 * </div>
37 * CSS
38 * #carousel
39 * {
40 * width: 700px;
41 * height: 150px;
42 * background-color: #111;
43 * position: absolute;
44 * top: 200px;
45 * left: 100px;
46 * }
47 * #carousel a
48 * {
49 * position: absolute;
50 * width: 110px;
51 * }
52 *
53 * @desc Creates a 3D carousel from all images inside div tag with id 'carousel'
54 *
55 *
56 * @name 3D Carousel
57 * @description Created a 3D Carousel from a list of images, with reflections and animated by mouse position
58 * @param Hash hash A hash of parameters
59 * @option String items items selection
60 * @option Integer itemWidth the max width for each item
61 * @option Integer itemHeight the max height for each item
62 * @option Integer itemMinWidth the minimum width for each item, the height is automaticaly calculated to keep proportions
63 * @option Float rotationSpeed the speed for rotation animation
64 * @option Float reflectionSize the reflection size a fraction from items' height
65 *
66 * @type jQuery
67 * @cat Plugins/Interface
68 * @author Stefan Petre
69 */
70jQuery.iCarousel = {
71
72 build : function(options)
73 {
74 return this.each(
75 function()
76 {
77 var el = this;
78 var increment = 2*Math.PI/360;
79 var maxRotation = 2*Math.PI;
80 if(jQuery(el).css('position') != 'relative' && jQuery(el).css('position') != 'absolute') {
81 jQuery(el).css('position', 'relative');
82 }
83 el.carouselCfg = {
84 items : jQuery(options.items, this),
85 itemWidth : options.itemWidth,
86 itemHeight : options.itemHeight,
87 itemMinWidth : options.itemMinWidth,
88 maxRotation : maxRotation,
89 size : jQuery.iUtil.getSize(this),
90 position : jQuery.iUtil.getPosition(this),
91 start : Math.PI/2,
92 rotationSpeed : options.rotationSpeed,
93 reflectionSize : options.reflections,
94 reflections : [],
95 protectRotation : false,
96 increment: 2*Math.PI/360
97 };
98 el.carouselCfg.radiusX = (el.carouselCfg.size.w - el.carouselCfg.itemWidth)/2;
99 el.carouselCfg.radiusY = (el.carouselCfg.size.h - el.carouselCfg.itemHeight - el.carouselCfg.itemHeight * el.carouselCfg.reflectionSize)/2;
100 el.carouselCfg.step = 2*Math.PI/el.carouselCfg.items.size();
101 el.carouselCfg.paddingX = el.carouselCfg.size.w/2;
102 el.carouselCfg.paddingY = el.carouselCfg.size.h/2 - el.carouselCfg.itemHeight * el.carouselCfg.reflectionSize;
103 var reflexions = document.createElement('div');
104 jQuery(reflexions)
105 .css(
106 {
107 position: 'absolute',
108 zIndex: 1,
109 top: 0,
110 left: 0
111 }
112 );
113 jQuery(el).append(reflexions);
114 el.carouselCfg.items
115 .each(
116 function(nr)
117 {
118 image = jQuery('img', this).get(0);
119 height = parseInt(el.carouselCfg.itemHeight*el.carouselCfg.reflectionSize);
120 if (jQuery.browser.msie) {
121 canvas = document.createElement('img');
122 jQuery(canvas).css('position', 'absolute');
123 canvas.src = image.src;
124 canvas.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity=60, style=1, finishOpacity=0, startx=0, starty=0, finishx=0)';
125
126 } else {
127 canvas = document.createElement('canvas');
128 if (canvas.getContext) {
129 context = canvas.getContext("2d");
130 canvas.style.position = 'absolute';
131 canvas.style.height = height +'px';
132 canvas.style.width = el.carouselCfg.itemWidth+'px';
133 canvas.height = height;
134 canvas.width = el.carouselCfg.itemWidth;
135 context.save();
136
137 context.translate(0,height);
138 context.scale(1,-1);
139
140 context.drawImage(
141 image,
142 0,
143 0,
144 el.carouselCfg.itemWidth,
145 height
146 );
147
148 context.restore();
149
150 context.globalCompositeOperation = "destination-out";
151 var gradient = context.createLinearGradient(
152 0,
153 0,
154 0,
155 height
156 );
157
158 gradient.addColorStop(1, "rgba(255, 255, 255, 1)");
159 gradient.addColorStop(0, "rgba(255, 255, 255, 0.6)");
160
161 context.fillStyle = gradient;
162 if (navigator.appVersion.indexOf('WebKit') != -1) {
163 context.fill();
164 } else {
165 context.fillRect(
166 0,
167 0,
168 el.carouselCfg.itemWidth,
169 height
170 );
171 }
172 }
173 }
174
175 el.carouselCfg.reflections[nr] = canvas;
176 jQuery(reflexions).append(canvas);
177 }
178 )
179 .bind(
180 'mouseover',
181 function(e)
182 {
183 el.carouselCfg.protectRotation = true;
184 el.carouselCfg.speed = el.carouselCfg.increment*0.1 * el.carouselCfg.speed / Math.abs(el.carouselCfg.speed);
185 return false;
186 }
187 )
188 .bind(
189 'mouseout',
190 function(e)
191 {
192 el.carouselCfg.protectRotation = false;
193 return false;
194 }
195 );
196 jQuery.iCarousel.positionItems(el);
197 el.carouselCfg.speed = el.carouselCfg.increment*0.2;
198 el.carouselCfg.rotationTimer = window.setInterval(
199 function()
200 {
201 el.carouselCfg.start += el.carouselCfg.speed;
202 if (el.carouselCfg.start > maxRotation)
203 el.carouselCfg.start = 0;
204 jQuery.iCarousel.positionItems(el);
205 },
206 20
207 );
208 jQuery(el)
209 .bind(
210 'mouseout',
211 function()
212 {
213 el.carouselCfg.speed = el.carouselCfg.increment*0.2 * el.carouselCfg.speed / Math.abs(el.carouselCfg.speed);
214 }
215 )
216 .bind(
217 'mousemove',
218 function(e)
219 {
220 if (el.carouselCfg.protectRotation == false) {
221 pointer = jQuery.iUtil.getPointer(e);
222 mousex = el.carouselCfg.size.w - pointer.x + el.carouselCfg.position.x;
223 el.carouselCfg.speed = el.carouselCfg.rotationSpeed * el.carouselCfg.increment * (el.carouselCfg.size.w/2 - mousex) / (el.carouselCfg.size.w/2);
224 }
225 }
226 );
227 }
228 );
229 },
230
231 positionItems : function(el)
232 {
233 el.carouselCfg.items.each(
234 function (nr)
235 {
236 angle = el.carouselCfg.start+nr*el.carouselCfg.step;
237 x = el.carouselCfg.radiusX*Math.cos(angle);
238 y = el.carouselCfg.radiusY*Math.sin(angle) ;
239 itemZIndex = parseInt(100*(el.carouselCfg.radiusY+y)/(2*el.carouselCfg.radiusY));
240 parte = (el.carouselCfg.radiusY+y)/(2*el.carouselCfg.radiusY);
241
242 width = parseInt((el.carouselCfg.itemWidth - el.carouselCfg.itemMinWidth) * parte + el.carouselCfg.itemMinWidth);
243 height = parseInt(width * el.carouselCfg.itemHeight / el.carouselCfg.itemWidth);
244 this.style.top = el.carouselCfg.paddingY + y - height/2 + "px";
245 this.style.left = el.carouselCfg.paddingX + x - width/2 + "px";
246 this.style.width = width + "px";
247 this.style.height = height + "px";
248 this.style.zIndex = itemZIndex;
249 el.carouselCfg.reflections[nr].style.top = parseInt(el.carouselCfg.paddingY + y + height - 1 - height/2) + "px";
250 el.carouselCfg.reflections[nr].style.left = parseInt(el.carouselCfg.paddingX + x - width/2) + "px";
251 el.carouselCfg.reflections[nr].style.width = width + "px";
252 el.carouselCfg.reflections[nr].style.height = parseInt(height * el.carouselCfg.reflectionSize) + "px";
253 }
254 );
255 }
256};
257jQuery.fn.Carousel = jQuery.iCarousel.build;